package com.jframe.sys.orm.service.impl;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;

import com.jframe.sys.controller.utils.QueryHelp;
import com.jframe.sys.orm.dao.BaseDao;
import com.jframe.sys.orm.service.BaseService;
import com.jframe.sys.orm.utils.ResultSet;
import com.jframe.sys.utils.ClassUtil;
import com.jframe.sys.utils.StringUtil;


public class BaseServiceImpl<T> extends ServiceImpl implements BaseService<T> {

	protected BaseDao dao;

	public BaseServiceImpl() {
		this.getPojoClz();
	}

	public void setDao(BaseDao dao) {
		this.dao = dao;
	}

	public T load(Serializable id) {
		return this.load(this.getPojoClz(), id);
	}

	public T load(String uniKeyField, Serializable id) {
		return this.load(this.getPojoClz(), uniKeyField, id);
	}

	public T load(Class clz, Serializable id) {
		return (T) dao.get(clz, id);
	}

	public T load(Class clz, String uniKeyField, Serializable id) {
		StringBuffer hql = new StringBuffer();
		hql.append(" from ");
		hql.append(clz.getSimpleName());
		hql.append(" where ");
		hql.append(uniKeyField);
		hql.append(" = ?");
		List<T> ls = this.dao.find(hql.toString(), id);
		try {
			T obj = null;
			if (ls.size() > 0) {
				obj = ls.get(0);
			} else {
				obj = (T) ClassUtil.setObjValue(clz.newInstance(), uniKeyField,
						id);
			}
			return obj;
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 保存
	 * 
	 * @param insertRecords
	 * @param updateRecords
	 * @param delRecords
	 */
	public void save(List<T> insertRecords, List<T> updateRecords,
			List<T> delRecords) {
		this.save(insertRecords);
		this.save(updateRecords);
		this.del(delRecords);
	}

	public void save(T obj) {
		this.dao.saveOrUpdate(obj);
	}

	public void save(List<T> objs) {
		for (T obj : objs) {
			this.save(obj);
		}
	}

	public void del(List<T> objs) {
		// TODO Auto-generated method stub
		for (T obj : objs) {
			this.del(obj);
		}
	}

	public void delete(String hql) {
		this.dao.execute(hql);
	}

	public void delete(String hql, Object param) {
		this.dao.execute(hql, param);
	}

	public void delete(String hql, Object[] params) {
		this.dao.execute(hql, params);
	}

	public void del(T obj) {
		this.dao.delete(obj);
	}

	@Override
	public List<T> findList(Class entiryClz, String condition) {
		// TODO Auto-generated method stub
		StringBuffer hql = new StringBuffer();
		hql.append(" from ");
		hql.append(entiryClz.getSimpleName());
		hql.append(" ");
		hql.append(condition);
		return this.dao.find(hql.toString());
	}

	@Override
	public void del(Class entiryClz, String ids) {
		// TODO Auto-generated method stub
		StringBuffer hql = new StringBuffer();
		hql.append(" delete from ").append(entiryClz.getSimpleName()).append(" where id in (:ids)");
		this.dao.delete(hql.toString(), ids);
	}

	@Override
	public void del(Class entiryClz, int id) {
		// TODO Auto-generated method stub
		StringBuffer hql = new StringBuffer();
		hql.append(" delete from ").append(entiryClz.getSimpleName()).append(" where id=?");
		this.dao.execute(hql.toString(),id);
	}

	@Override
	public void del(String ids) {
		// TODO Auto-generated method stub
		this.del(this.getPojoClz(), ids);
	}

	@Override
	public void del(int id) {
		// TODO Auto-generated method stub
		this.del(this.getPojoClz(), id);
	}

	@Override
	public void del(Serializable id, String unikeyField) {
		// TODO Auto-generated method stub
		String clzName = this.getPojoClz().getSimpleName();
		StringBuffer hql = new StringBuffer();
		hql.append(" delete from ").append(clzName).append(" where ").append(unikeyField).append("=?");
		this.delete(hql.toString(), id);
	}

	@Override
	public void del(Class clz, Serializable id, String unikeyField) {
		StringBuffer hql = new StringBuffer();
		hql.append(" delete from ").append(clz.getSimpleName()).append(" where ").append(unikeyField).append("=?");
		this.delete(hql.toString(), id);
	}

	@Override
	public List<T> findAll() {
		// TODO Auto-generated method stub
		return this.findAll(this.getPojoClz());
	}

	@Override
	public List<T> findAll(String clz) {
		// TODO Auto-generated method stub
		return this.dao.find(new StringBuffer(" from ").append(clz).toString());
	}

	@Override
	public List<T> findAll(Class clz) {
		// TODO Auto-generated method stub
		return this.findAll(clz.getSimpleName());
	}

	@Override
	public List<T> findList(T entiryClz, String condition) {
		// TODO Auto-generated method stub
		StringBuffer hql = new StringBuffer();
		hql.append(" from ").append(entiryClz.getClass().getSimpleName()).append(" ").append(condition);
		return this.dao.find(hql.toString());
	}

	@Override
	public List<T> find(String hql) {
		// TODO Auto-generated method stub
		return this.dao.find(hql);
	}

	@Override
	public List<T> findListByHql(String hql) {
		// TODO Auto-generated method stub
		return this.dao.find(hql);
	}

	@Override
	public List<T> find(String hql, Object obj) {
		// TODO Auto-generated method stub
		return this.dao.find(hql, obj);
	}

	@Override
	public List<T> find(String hql, Object[] objs) {
		// TODO Auto-generated method stub
		return this.dao.find(hql, objs);
	}

	@Override
	public List<T> findList(String condition) {
		// TODO Auto-generated method stub
		return this.findList(this.getPojoClz(), condition);
	}

	public List<T> findBySql(String sql) {
		return this.findBySql(this.getPojoClz(), sql);
	}

	@Override
	public List<T> findBySql(String sql, Object obj) {
		return this.findBySql(sql, new Object[] { obj });
	}

	@Override
	public List<T> findBySql(String sql, Object[] objs) {
		return this.findBySql(this.getPojoClz(), sql, objs);
	}

	@Override
	public List<T> findList(Class entiryClz, String condition, Object param,
			int start, int limit) {
		// TODO Auto-generated method stub
		StringBuffer hql = new StringBuffer();
		hql.append(" from ").append(entiryClz.getSimpleName()).append(" ").append(condition);
		return this.dao.find(hql.toString(), param, start, limit);
	}

	@Override
	public List<T> findList(Class entiryClz, String condition, Object[] params,
			int start, int limit) {
		// TODO Auto-generated method stub
		StringBuffer hql = new StringBuffer();
		hql.append(" from ").append(entiryClz.getSimpleName()).append(" ").append(condition);
		return this.dao.find(hql.toString(), params, start, limit);
	}

	@Override
	public List<T> findList(String condition, Object param, int start, int limit) {
		// TODO Auto-generated method stub
		StringBuffer hql = new StringBuffer();
		hql.append(" from ").append(this.getPojoClz().getSimpleName()).append(" ").append(condition);
		return this.dao.find(hql.toString(), param, start, limit);
	}

	@Override
	public List<T> findList(String condition, Object[] params, int start,
			int limit) {
		// TODO Auto-generated method stub
		StringBuffer hql = new StringBuffer();
		hql.append(" from ").append(this.getPojoClz().getSimpleName()).append(" ").append(condition);
		return this.dao.find(hql.toString(), params, start, limit);
	}

	@Override
	public ResultSet<T> findListByPage(Class entiryClz, String condition,
			int start, int limit) {
		StringBuffer hql = new StringBuffer();
		hql.append(" from ").append(entiryClz.getSimpleName()).append(" ").append(condition);
		ResultSet<T> rs = new ResultSet<T>();
		rs.setRows(this.dao.find(hql.toString(), start, limit));
		rs.setTotal(this.dao.queryForIntByHql(hql.toString()));
		return rs;
	}

	@Override
	public ResultSet<T> findListByPage(String condition, int start, int limit) {
		return this.findListByPage(this.getPojoClz(), condition, start, limit);
	}

	@Override
	public ResultSet<T> findListByPage(String condition, Object param,
			int start, int limit) {
		// TODO Auto-generated method stub
		StringBuffer hql = new StringBuffer();
		hql.append(" from ").append(this.getPojoClz().getSimpleName()).append(" ").append(condition);
		List<T> ls = this.dao.find(hql.toString(), param, start, limit);
		ResultSet<T> rs = new ResultSet<T>();
		rs.setRows(ls);
		rs.setTotal(this.dao.queryForIntByHql(hql.toString(), param));
		return rs;
	}

	@Override
	public ResultSet<T> findListByPage(String condition, Object[] params,
			int start, int limit) {
		// TODO Auto-generated method stub
		StringBuffer hql = new StringBuffer();
		hql.append(" from ").append(this.getPojoClz().getSimpleName()).append(" ").append(condition);
		List<T> ls = this.dao.find(hql.toString(), params, start, limit);
		ResultSet<T> rs = new ResultSet<T>();
		rs.setRows(ls);
		rs.setTotal(this.dao.queryForIntByHql(hql.toString(), params));
		return rs;
	}
	
	

	@Override
	public ResultSet<T> findListByPageIds(String ids, int start, int limit) {
		// TODO Auto-generated method stub
		StringBuffer hql = new StringBuffer();
		hql.append(" from ").append(this.getPojoClz().getSimpleName()).append(" where id in (:ids)");
		ResultSet<T> rs = new ResultSet<T>();
		rs.setRows(this.dao.findByIds(hql.toString(), ids, start, limit));
		rs.setTotal(this.dao.queryForIntByHql(hql.toString(), ids));
		return rs;
	}

	@Override
	public ResultSet<T> findListByHql(String hql, int start, int limit) {
		ResultSet<T> rs = new ResultSet<T>();
		rs.setRows(this.dao.find(hql, start, limit));
		rs.setTotal(this.dao.queryForIntByHql(hql));
		return rs;
	}

	@Override
	public Class getPojoClz() {
		// TODO Auto-generated method stub
		if (this.pojoClz == null) {
			this.pojoClz = this.getGenericType(0);
		}
		return this.pojoClz;
	}

	private Class getGenericType(int index) {
		Type genType = getClass().getGenericSuperclass();
		if (!(genType instanceof ParameterizedType)) {
			return Object.class;
		}
		Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
		if (index >= params.length || index < 0) {
			throw new RuntimeException("Index outof bounds");
		}
		if (!(params[index] instanceof Class)) {
			return Object.class;
		}
		return (Class) params[index];
	}

	@Override
	public ResultSet<T> findListByPage(QueryHelp queryHelp, String conditions,String orderby) {
		// TODO Auto-generated method stub
		ResultSet<T> rs = new ResultSet<T>();
		StringBuffer hql = new StringBuffer();
		//hql.append(" from ").append(this.getPojoClz().getSimpleName()).append(" where ").append(queryHelp.getQueryStr()).append(" ").append(conditions);
		
		hql.append(" from ").append(this.getPojoClz().getSimpleName());
		if(StringUtil.isStringNull(conditions)){
			if(!StringUtil.isStringNull(queryHelp.getQueryStr())){
				hql.append(" where ");
				hql.append(StringUtil.removeBeginStr(queryHelp.getQueryStr()));
			}			
		}else{							
			if(!StringUtil.isStringNull(queryHelp.getQueryStr())){
				hql.append(" where ");
				hql.append(StringUtil.removeBeginStr(queryHelp.getQueryStr()));
				hql.append(" ");
				hql.append(conditions);
			}else{
				hql.append(" where ");
				hql.append(StringUtil.removeBeginStr(conditions));
			}				
		}
		hql.append(" ");
		hql.append(orderby);
		List<T> ls = this.dao.find(hql.toString(), queryHelp.getParams());
		rs.setRows(ls);
		rs.setTotal(ls.size());
		return rs;
	}

	@Override
	public ResultSet<T> findListByPage(QueryHelp queryHelp, String conditions,String orderby,int start, int limit) {
		// TODO Auto-generated method stub
		boolean isWhereExist=false;
		ResultSet<T> rs = new ResultSet<T>();
		StringBuffer hql = new StringBuffer();
		hql.append(" from ").append(this.getPojoClz().getSimpleName());
		if(StringUtil.isStringNull(conditions)){
			if(!StringUtil.isStringNull(queryHelp.getQueryStr())){
				hql.append(" where ");
				hql.append(StringUtil.removeBeginStr(queryHelp.getQueryStr()));
			}			
		}else{							
			if(!StringUtil.isStringNull(queryHelp.getQueryStr())){
				hql.append(" where ");
				hql.append(StringUtil.removeBeginStr(queryHelp.getQueryStr()));
				hql.append(" ");
				hql.append(conditions);
			}else{
				hql.append(" where ");
				hql.append(StringUtil.removeBeginStr(conditions));
			}				
		}
		hql.append(" ");
		hql.append(orderby);
		rs.setRows(this.dao.find(hql.toString(), queryHelp.getParams(),start, limit));
		rs.setTotal(this.dao.queryForIntByHql(hql.toString(),queryHelp.getParams()));
		return rs;
	}

	@Override
	public ResultSet<T> findListByPage(QueryHelp queryHelp, String conditions,String orderby,Object param, int start, int limit) {
		// TODO Auto-generated method stub
		Object[] params = queryHelp.getParams();
		ResultSet<T> rs = new ResultSet<T>();
		if (params == null) {
			StringBuffer hql = new StringBuffer();
			//hql.append(" from ").append(this.getPojoClz().getSimpleName()).append(" where 1=1 ").append(queryHelp.getQueryStr()).append(" ").append(conditions);
			
			hql.append(" from ").append(this.getPojoClz().getSimpleName());
			if(StringUtil.isStringNull(conditions)){
				if(!StringUtil.isStringNull(queryHelp.getQueryStr())){
					hql.append(" where ");
					hql.append(StringUtil.removeBeginStr(queryHelp.getQueryStr()));
				}			
			}else{							
				if(!StringUtil.isStringNull(queryHelp.getQueryStr())){
					hql.append(" where ");
					hql.append(StringUtil.removeBeginStr(queryHelp.getQueryStr()));
					hql.append(" ");
					hql.append(conditions);
				}else{
					hql.append(" where ");
					hql.append(StringUtil.removeBeginStr(conditions));
				}				
			}
			hql.append(" ");
			hql.append(orderby);
			
			rs.setRows(this.dao.find(hql.toString(), param, start, limit));
			rs.setTotal(this.dao.queryForIntByHql(hql.toString(), param));
			return rs;
		} else {
			Object[] objs = new Object[queryHelp.getParams().length + 1];
			for (int i = 0; i < params.length; i++) {
				objs[i] = params[i];
			}
			objs[params.length] = param;
			StringBuffer hql = new StringBuffer();
			//hql.append(" from ").append(this.getPojoClz().getSimpleName()).append(" where 1=1 ").append(queryHelp.getQueryStr()).append(" ").append(conditions);
			
			hql.append(" from ").append(this.getPojoClz().getSimpleName());
			if(StringUtil.isStringNull(conditions)){
				if(!StringUtil.isStringNull(queryHelp.getQueryStr())){
					hql.append(" where ");
					hql.append(StringUtil.removeBeginStr(queryHelp.getQueryStr()));
				}			
			}else{							
				if(!StringUtil.isStringNull(queryHelp.getQueryStr())){
					hql.append(" where ");
					hql.append(StringUtil.removeBeginStr(queryHelp.getQueryStr()));
					hql.append(" ");
					hql.append(conditions);
				}else{
					hql.append(" where ");
					hql.append(StringUtil.removeBeginStr(conditions));
				}				
			}
			hql.append(" ");
			hql.append(orderby);
			
			rs.setRows(this.dao.find(hql.toString(), objs, start, limit));
			rs.setTotal(this.dao.queryForIntByHql(hql.toString(), objs));
			return rs;
		}

	}
	
	/**
	 *  conditions " and key1=? and ......"
	 */
	@Override
	public ResultSet<T> findListByPage(QueryHelp queryHelp, String conditions,String orderby,Object[] params, int start, int limit) {
		// TODO Auto-generated method stub
		Object[] values = queryHelp.getParams();
		ResultSet<T> rs = new ResultSet<T>();
		if (values == null) {
			StringBuffer hql = new StringBuffer();
			//hql.append(" from ").append(this.getPojoClz().getSimpleName()).append(" where 1=1 ").append(queryHelp.getQueryStr()).append(" ").append(conditions);
			
			hql.append(" from ").append(this.getPojoClz().getSimpleName());
			if(StringUtil.isStringNull(conditions)){
				if(!StringUtil.isStringNull(queryHelp.getQueryStr())){
					hql.append(" where ");
					hql.append(StringUtil.removeBeginStr(queryHelp.getQueryStr()));
				}			
			}else{							
				if(!StringUtil.isStringNull(queryHelp.getQueryStr())){
					hql.append(" where ");
					hql.append(StringUtil.removeBeginStr(queryHelp.getQueryStr()));
					hql.append(" ");
					hql.append(conditions);
				}else{
					hql.append(" where ");
					hql.append(StringUtil.removeBeginStr(conditions));
				}				
			}
			hql.append(" ");
			hql.append(orderby);
			
			rs.setRows(this.dao.find(hql.toString(), params, start, limit));
			rs.setTotal(this.dao.queryForIntByHql(hql.toString(), params));
			return rs;
		} else {
			Object[] objs = new Object[queryHelp.getParams().length + 1];
			for (int i = 0; i < values.length; i++) {
				objs[i] = values[i];
			}
			for (int i = values.length; i < values.length + params.length; i++) {
				objs[values.length] = params[i - values.length];
			}
			StringBuffer hql = new StringBuffer();
			hql.append(" from ").append(this.getPojoClz().getSimpleName());
			if(StringUtil.isStringNull(conditions)){
				if(!StringUtil.isStringNull(queryHelp.getQueryStr())){
					hql.append(" where ");
					hql.append(StringUtil.removeBeginStr(queryHelp.getQueryStr()));
				}
			}else{							
				if(!StringUtil.isStringNull(queryHelp.getQueryStr())){
					hql.append(" where ");
					hql.append(StringUtil.removeBeginStr(queryHelp.getQueryStr()));
					hql.append(" ");
					hql.append(conditions);
				}else{
					hql.append(" where ");
					hql.append(StringUtil.removeBeginStr(conditions));
				}				
			}
			hql.append(" ");
			hql.append(orderby);
			rs.setRows(this.dao.find(hql.toString(), objs, start, limit));
			rs.setTotal(this.dao.queryForIntByHql(hql.toString(), objs));
			return rs;
		}
	}

	@Override
	public List<T> findListByIds(String ids) {
		// TODO Auto-generated method stub
		StringBuffer hql = new StringBuffer();
		hql.append(" from ").append(this.getPojoClz().getSimpleName()).append(" where id in (:ids)");	
		return this.dao.findByIds(hql.toString(), ids);
	}

	@Override
	public List<T> findListByIds(String ids, int start, int limit) {
		// TODO Auto-generated method stub
		StringBuffer hql = new StringBuffer();
		hql.append(" from ").append(this.getPojoClz().getSimpleName()).append(" where id in (:ids)");	
		return this.dao.findByIds(hql.toString(), ids,start,limit);
	}
	
	/**
	 * 功能说明：过滤字段中的sql注入.
	 * @param field
	 * @return
	 */
	protected  String filterField(String field) {  

		 String inj_str = "',and,exec,insert,select,delete,update,count,*,%,chr,mid,master,truncate,char,declare,;,or,-,+";
		 String inj_stra[] = inj_str.split(",");
		 for (int i=0 ; i < inj_stra.length ; i++ )
		 {
			 String  a =inj_stra[i];
			 if (field.indexOf(a)!=-1)
			 {
				field="";
				break;
			 }
		 }		 
		 return field;
	} 
	
	
	

}
